package org.smog.core.config.security.filter;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.smog.core.config.security.jwt.JwtProperties;
import org.smog.core.config.security.jwt.JwtTokenUtil;
import org.smog.core.config.security.model.IAuthUser;
import org.smog.core.exception.AuthExpiredFriendlyException;
import org.smog.core.exception.AuthInvalidFriendlyException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;

/**
 * @Description: Created by IntelliJ IDEA.
 * @project_name: smogTemp
 * @time: 2020-05-14 15:10
 * @email: 17685306043@163.com
 * @author: huangZhongYao
 */
@Slf4j
@Component
@AllArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    JwtProperties jwtProperties;
    JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        // 获取请求头中token
        String authHeader = httpServletRequest.getHeader(this.jwtProperties.getHeader());
        if (authHeader != null && authHeader.startsWith(this.jwtProperties.getTokenPrefix())) {
            // 去除token中的前缀
            authHeader = authHeader.replace(this.jwtProperties.getTokenPrefix(), "");

            // 验证token
            if (jwtTokenUtil.validateToken(authHeader)) {
                throw new AuthInvalidFriendlyException("AuthInvalid");
            }

            if (this.jwtProperties.isExpirationVerificationEnable()) {
                Boolean tokenExpired = this.jwtTokenUtil.isTokenExpired(authHeader);
                if (tokenExpired) {
                    throw new AuthExpiredFriendlyException("AuthExpired");
                }
            }
            // token转换为认证用户
            IAuthUser authUser = this.jwtTokenUtil.toAuthUser(authHeader);
            // 获取token中的角色权限标识
            Collection<? extends GrantedAuthority> authorities = this.jwtTokenUtil.getAuthorities(authHeader);

            /*将用户信息设置到上下文 方便后续逻辑处理*/
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(authUser, (Object) null, authorities);
            authentication.setDetails((new WebAuthenticationDetailsSource()).buildDetails(httpServletRequest));

            logger.info(String.format("已认证  %s 用户详细信息, 设置安全上下文!", authUser.getUserName()));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}
